require "lfs"
require "unity"
require "luaMPI"
local MPIModel = require "MPIModel"
local nl = require "luaNumeric"
----------------------------------------------------------------------------
--初始化参数
local GratingModel = MPIModel:new( { 
	dext = 8;                                    -- 物体到空气盒子
	probe_info = { lambda=nl.LinearSpace(500,700,20); dext = 100; };
	source_info = { freq_min = 5; freq_max = 10;  dsrc  = 0; polarization_angle = 0, theta = 45; };
	boundary = { xm=Periodic; xp=Periodic; ym=Periodic;yp=Periodic;zm=UPML;zp=UPML;};
	units = { freq = THz; dim = nm };
	mesh_freq = 250;
	name = "grating";
	save2file = false;
	camera = "3377.21 -3356.18 2213.26 0.4964 0.205616 0.322752 0.779192";
	record_ref = true;
	record_tran = true;
	modes = { {0,0},{-1,0},{1,0} };
})
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--初始化
function GratingModel:init()
	-- local geo = self.geo_ or _geo
	collectgarbage()
	print("collectgarbage");
	collectgarbage()
	
	print( "Geometry clear all objects")
	Geometry.clear_all();
	
	print( "init" )
	self:set_threads();
	self:set_boundary();
	self:set_units();
	self:set_mesh_freq();
	self:create_geometry();
	self:create_source();
	self:create_probe();
	self:create_grabber();
	self:perspective_view();
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建平面波源
function GratingModel:create_source ()

	print( "create srouce")	
	-------------------------------------
	-- local type = self.source_info.type;
	local freqmin = self.source_info.freq_min; 
	local freqmax = self.source_info.freq_max;
	local dsrc = self.source_info.dsrc or 0;
	local angle = self.source_info.polarization_angle;
	local theta = self.source_info.theta;
	assert(freqmin,"freqmin is not set in source function(.source_info.freqmin_)");
	assert(freqmax,"freqmax is not set in source function(.source_info.freqmax_)");
	-- assert(type,"src type is not set in source function(self.type_)");
	-------------------------------------

	-------------------------------------
	--Pulse
	local signal_gauss = Geometry.NewGaussPulse("Gauss Pulse")
	signal_gauss :freq_low(freqmin)
	signal_gauss :freq_high(freqmax)
	self.psig = signal_gauss
	-------------------------------------


	-------------------------------------
	--Source
	local src= Geometry.PlaneWaveSrc:new();              
	src :name("Polarization_Angle:"..angle)
	src :polarization_angle(angle)
	src :pt1(self.bbox:xmin() , self.bbox:ymin() ,  self.bbox:zmax() - dsrc)
	src :pt2(self.bbox:xmax() , self.bbox:ymax() , self.bbox:zmax() - dsrc)
	src :signal(self.psig)
	src :direction(forward)
	src :point_size(2)

	-- src:enable_plane(yx)
	-- src:enable_plane(yz)
	-- src:enable_plane(zy)
	-- src:enable_plane(xz)
	-- src:enable_plane(zx)
	--src :is_point(false)
	 -- src :is_fill(false)
	--src :is_OutLine(true)
	src:rotate_uvw(yAxis,180)
	src:rotate_uvw(yAxis,theta)
	src :outline_width(1.5)
	Geometry.AddSrc(src)
	-------------------------------------
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建Probe
function GratingModel:create_probe ()

	print( "create probe")	
	local dext = self.probe_info.dext
	local strFreq="";
	for k,v in pairs (self.probe_info.lambda) do
		strFreq = strFreq..v..";"
	end
	---------------------------
	--Bloch port
	if self.record_ref then
		local pbr = Geometry.BlochPort:new("reflection")
		pbr :pt1(self.bbox:xmin(),  self.bbox:ymin(),self.bbox:zmax()-dext)
		pbr :pt2(self.bbox:xmax(), self.bbox:ymax(),self.bbox:zmax()-dext)
		pbr :fields_type(sz)
		pbr :av_vector(0, self.bbox:ysize(),0);
		pbr :au_vector(self.bbox:xsize(),0,0);
		for k,v in pairs(self.modes) do
		    pbr :add_mode(v[1],v[2]);
		end
		pbr :lambda(strFreq)
		pbr :is_fill(false)
		pbr :signal(self.psig )	
		Geometry.AddProbe(pbr)
	end
	----------------------------
	
	---------------------------
	--Bloch port
	if self.record_tran then
		local pbt = Geometry.BlochPort:new("transmission")
		-- local pbr = Geometry.SurfaceProbe:new("reflection")
		pbt :pt1(self.bbox:xmin(),  self.bbox:ymin(),self.bbox:zmin()+dext)
		pbt :pt2(self.bbox:xmax(), self.bbox:ymax(),self.bbox:zmin()+dext)
		pbt :fields_type(sz)
		pbt :av_vector(0, self.bbox:ysize(),0);
		pbt :au_vector(self.bbox:xsize(),0,0);
		for k,v in pairs(self.modes) do
		    pbt :add_mode(v[1],v[2]);
		end	
		pbt :lambda(strFreq)
		pbt :is_fill(false)
		pbt :signal(self.psig )	
		Geometry.AddProbe(pbt)
	end
	----------------------------
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建Grabber
function MPIModel:create_grabber(  )
	print( "create grabber")	
	 local cm = Geometry.CGLColorMap:new("Jet")
	 local  probe = Geometry.TransientFieldsGrabber:new();
	 probe :name("Grabber-xy("..self.name..")");
	 probe :camera(self.camera)
	  probe :save2file(self.save2file);
	 probe :frame_delay(20);
	 probe :size(600,450);
	 probe :add_slice(cm,scalar_e,yz,0,2,false)
	 probe :add_slice(cm,scalar_e,zx,0,2,false)
	 -- probe :add_slice(cm,ez,yz,0,2)
	  -- probe :is_fill(false);
	 -- probe:fields_types(ez,hx)
	 probe :stride(20);
	 Geometry.AddTransientFieldsGrabber(probe)
	----------------------------
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--后处理
function GratingModel:post_run ()
	print( "update probe" )
	-- Geometry.find_probe("fbox") :update()
	-- Geometry.find_probe("fbox") :save( self.name..".txt", "dBsm" )
	Geometry.SaveGeometry( self.name..".gap")
end
-----------------------------------------------------------------------------

return GratingModel;
